home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / a86v302b.arc / 08EXPR.DOC < prev    next >
Text File  |  1987-04-08  |  24KB  |  630 lines

  1. CHAPTER 8   NUMBERS AND EXPRESSIONS                       8-1
  2.  
  3. Numbers and Bases
  4.  
  5. A86 supports a variety of formats for numbers.  In non-computer 
  6. life, we write numbers in a decimal format.  There are ten 
  7. digits, 0 through 9, that we use to describe numbers; and each 
  8. digit-position is ten times as significant as the position to its 
  9. right.   The number ten is called the "base" of the decimal 
  10. format.  Computer programmers often find it convenient to use 
  11. other bases to specify numbers used in their programs.  The most 
  12. commonly-used bases are two (binary format), sixteen (hexadecimal 
  13. format), and eight (octal format).  
  14.  
  15. The hexadecimal format requires sixteen digits.  The extra six 
  16. digits beyond 0 through 9 are denoted by the first six letters of 
  17. the alphabet: A for ten, B for eleven, C for twelve, D for 
  18. thirteen, E for fourteen, and F for fifteen.  
  19.  
  20. In A86, a number must always begin with a digit from 0 through 9, 
  21. even if the base is hexadecimal.  This is so that A86 can 
  22. distinguish between a number and a symbol that happens to have 
  23. digits in its name.  If a hexadecimal number would begin with a 
  24. letter, you precede the letter with a zero.  For example, hex A0, 
  25. which is the same as decimal 160, would be written 0A0.  
  26.  
  27. Because it is necessary for you to append leading zeroes to many 
  28. hex numbers, and because you never have to do so for decimal 
  29. numbers, I decided to make hexadecimal the default base for 
  30. numbers with leading zeroes.  Decimal is still the default base 
  31. for numbers beginning with 1 through 9.  
  32.  
  33. Large numbers can be given as the operands to DD, DQ, or DT 
  34. directives.  For readability, you may freely intersperse 
  35. underscore characters anywhere with your numbers.
  36.  
  37. The default base can be overridden, with a letter or letters at 
  38. the end of the number: B or xB for binary, O or Q for octal, H or 
  39. R for hexadecimal, and D or xD for decimal.  Examples: 
  40.  
  41.  077Q     octal, value is 8*7 + 7 = 63 in decimal notation
  42.  123O     octal, if the "O" is a letter: 64 + 2*8 + 3 = 83 decimal
  43.  1230     decimal 1230, showing why you should use "Q" for octal!!
  44.  01234567H                   large constant
  45.  0001_0000_0000_0000_0003R   real number specified in hexadecimal 
  46.  100D     superfluous D indicates decimal base
  47.  0100D    hex number 100D, which is 4096 + 13 = 5009 in decimal
  48.  0100xD   decimal 100, since xD overrides the default hex-format
  49.  0110B    hex 110B, which is 4096 + 256 + 11 = 5263 in decimal
  50.  0110xB   binary 4+2 = 6 in decimal notation
  51.  110B     also binary 4+2 = 6, since "B" is not a decimal-digit
  52.  
  53. The last five examples above illustrate why an "x" is sometimes 
  54. necessary before the base-override letter "B" or "D".  If that 
  55. letter can be interpreted as a hex digit, it is; the "x" forces 
  56. an override-interpretation for the "B" or "D".  By the way, the 
  57. usage of lower-case for x and upper-case for the following 
  58. override-letter is simply a recommendation; A86 always treats 
  59. upper-and lower-case letters equivalently.  
  60.                                                           8-2
  61. The RADIX Directive
  62.  
  63. The above-mentioned set of defaults (hex if leading zero, decimal 
  64. otherwise) can be overridden with the RADIX directive.  The RADIX 
  65. directive consists of the word RADIX followed by a number from 2 
  66. to 16.  The default base for the number is ALWAYS decimal, 
  67. regardless of any (or no) previous RADIX commands.  The number 
  68. gives the default base for ALL subsequent numbers, up to (but not 
  69. including) the next RADIX command.  If there is no number 
  70. following RADIX, then A86 returns to its initial mixed-default of 
  71. hex for leading zeroes, decimal for other leading digits.  
  72.  
  73. For compatibility with IBM's assembler, RADIX can appear with a 
  74. leading period; although I curse the pinhead-designer who put 
  75. that period into IBM's language.  
  76.  
  77. As an alternative to the RADIX directive, I provide the D-switch, 
  78. which causes A86 to start with decimal defaults.  You can put +D 
  79. into the A86 command invocation, or into the A86 environment 
  80. variable.  The first RADIX command in the program will override 
  81. the D switch setting.
  82.  
  83. Following are examples of radix usage.  The numbers in the 
  84. comments are all in decimal notation.  
  85.  
  86.   DB 10,010     ; produces 10,16 if RADIX was not seen yet
  87.                 ;   and +D switch was not specified
  88. RADIX 10
  89.   DB 10,010     ; produces 10,10
  90. RADIX 16
  91.   DB 10,010     ; produces 16,16
  92. RADIX 2
  93.   DB 10,01010   ; produces 2,10
  94. RADIX 3         ; for Martian programmers in Heinlein novels
  95.   DB 10,100     ; produces 3,9
  96. RADIX
  97.   DB 10,010     ; produces 10,16
  98.  
  99.  
  100.                                                           8-3
  101.  
  102. Floating-point Initializations
  103.  
  104. A86 allows floating-point numbers as the operands to DD, DQ, and 
  105. DT directives.  The numbers are encoded according to the IEEE 
  106. standard, followed by the 8087 and 80287 coprocessors.  The 
  107. format for floating-point constants is as follows: First, there 
  108. is a decimal number containing a decimal point.  There must be a 
  109. decimal point, or else the number is interpreted as an integer.  
  110. There must also be at least one decimal digit, either to the left 
  111. or right of the decimal point, or else the decimal point is 
  112. interpreted as an addition (structure-element) operator.  
  113. Optionally, there may follow immediately after the decimal number 
  114. the letter E followed by a decimal number.  The E stands for 
  115. "exponent", and means "times 10 raised to the power of".  You may 
  116. provide a + or - between the E and its number.  Examples:
  117.  
  118.   0.1             constant one-tenth
  119.   .1              the same
  120.   300.            floating-point three hundred
  121.   30.E1           30 * 10**1; i.e., three hundred
  122.   30.E+1          the same
  123.   30.E-1          30 * 10**-1; i.e., three
  124.   30E1            not floating-point: hex integer 030E1 
  125.   1.234E20        scientific notation: 1.234 times 10 to the 20th
  126.   1.234E-20       a tiny number: 1.234 divided by 10 to the 20th
  127.  
  128.  
  129.  
  130. Overview of Expressions
  131. -------- -- -----------
  132.  
  133. Most of the operands that you code into your instructions and 
  134. data initializations will be simple register names, variable 
  135. names, or constants.  However, you will regularly wish to code 
  136. operands that are the results of an arithmetic calculation, 
  137. performed either by the machine when the program is running (for 
  138. indexing), or by the assembler (to determine the value to 
  139. assemble into the program).  A86 has a full set of operators that 
  140. you can use to create expressions to cover these cases: 
  141.  
  142. * Arithmetic Operators
  143.                  byte isolation and combination (HIGH, LOW, BY)
  144.                  addition and subtraction (+,-)
  145.                  multiplication and division (* , /, MOD)
  146.                  shifting operators (SHR, SHL, BIT)
  147.  
  148. * Logical Operators
  149.                  (AND, OR, XOR, NOT)
  150.  
  151. * Relational Operators
  152.                  (EQ, LE, LT, GE, GT, NE)
  153.                                                           8-4
  154. * Attribute Operators/Specifiers
  155.                  size specifiers (B=BYTE,W=WORD,F=FAR,SHORT,LONG)
  156.                  attribute specifiers (OFFSET,NEAR,brackets)
  157.                  segment-addressing specifier (:)
  158.                  compatibility operators (PTR,ST)
  159.                  built-in value specifiers (TYPE,THIS,$)
  160.  
  161. * Special Data Duplication Operator
  162.                  (DUP)  --see Chapter 9 for a description
  163.  
  164.  
  165. Types of Expression Operands
  166. ----- -- ---------- --------
  167.  
  168. Numbers and Label Addresses
  169.  
  170. A number or constant (16-bit number) can be used in most 
  171. expressions.   A label (defined with a colon) is also treated as 
  172. a constant and so can be used in expressions, except when it is a 
  173. forward reference.  
  174.  
  175.  
  176. Variables
  177.  
  178. A variable stands for a byte- or word-memory location.   You may 
  179. add or subtract constants from variables; when you do so, the 
  180. constant is added to the address of the variable.  You typically 
  181. do this when the variable is the name of a memory array.  
  182.  
  183.  
  184. Index Expressions
  185.  
  186. An index expression consists of a combination of a base register 
  187. [BX] or [BP], and/or an index register [SI] or [DI], with an 
  188. optional constant added or subtracted.   You will usually want to 
  189. precede the bracketed expression with B, W, or F; to specify the 
  190. kind of memory unit (byte, word, or far-pointer) you are 
  191. referring to.  The expression stands for the memory unit whose 
  192. address is the run-time value(s) of the base and/or index 
  193. registers added to the constant.  See the Effective Address 
  194. section and the beginning of this chapter for more details on 
  195. indexed memory.  
  196.  
  197.  
  198. Arithmetic Operators
  199. ---------- ---------
  200. HIGH/LOW
  201.  
  202. Syntax: HIGH operand
  203.         LOW operand
  204.  
  205. These operators are called the "byte isolation" operators.  The 
  206. operand  must evaluate to a 16-bit number.   HIGH returns the 
  207. high-order byte of the number; LOW the low-order byte.  
  208.  
  209. For example,
  210.  
  211.   MOV AL,HIGH(01234)       ; AL = 012
  212.   TENHEX EQU LOW(0FF10)    ; TENHEX = 010
  213.                                                           8-5
  214. These operators can be applied to each other.   The following 
  215. identities apply: 
  216.  
  217. LOW LOW Q = LOW Q
  218. LOW HIGH Q = HIGH Q
  219. HIGH LOW Q = 0
  220. HIGH HIGH Q = 0
  221.  
  222.  
  223. BY
  224.  
  225. Syntax:  operand BY operand
  226.  
  227. This operator is a "byte combination" operator.  It returns the 
  228. word whose high byte is the left operand, and whose low byte is 
  229. the right operand.  For example, the expression 3 BY 5 is the 
  230. same as hexadecimal 0305.  The BY operator is exclusive to A86.  
  231. I added it to cover the following situation: Suppose you are 
  232. initializing your registers to immediate values.  Suppose you 
  233. want to initialize AH to the ASCII value 'A', and AL to decimal 
  234. 10.  You could code this as two instructions MOV AH,'A' and MOV 
  235. AL,10; but you realize that a single load into the AX register 
  236. would save both program space and execution time.  Without the BY 
  237. operator, you would have to code MOV AX,0410A, which disguises 
  238. the types of the individual byte-operands you were thinking 
  239. about.  With BY, you can code it properly: MOV AX,'A' BY 10.  
  240.  
  241.  
  242. Addition (combination)
  243.  
  244. Syntax: operand + operand
  245.         operand.operand
  246.         operand PTR operand
  247.         operand operand
  248.  
  249. As shown in the above syntax, addition can be accomplished in 
  250. four ways: with a plus sign, with a dot operator, with a PTR 
  251. operator, and simply by juxtaposing two operands next to each 
  252. other.  The dot and PTR operators are provided for compatibility 
  253. with Intel/IBM assemblers.  The dot is used in structure-field 
  254. notation; PTR is used in expressions such as BYTE PTR 0.  (See 
  255. Chapter 12 for recommendations concerning PTR.) 
  256.  
  257. If either operand is a constant, the answer is an expression with 
  258. the typing of the other operand, with the offsets added.  For 
  259. example, if BVAR is a byte variable, then BVAR + 100 is the byte 
  260. variable 100 bytes beyond BVAR.  
  261.  
  262. Other examples:
  263.    DB 100+17         ; simple addition
  264.    CTRL EQU -040
  265.    MOV AL,CTRL'D'    ; a nice notation for control-D!
  266.    MOV DX,[BP].SMEM  ; --where SMEM was in an unindexed structure
  267.    DQ  10.0 + 7.0    ; floating-point addition
  268.                                                           8-6
  269. Subtraction
  270.  
  271. Syntax: operand - operand
  272.  
  273. The subtraction operator may have operands that are:
  274.  
  275. a.  both absolute numbers
  276. b.  variable names that have the same type
  277.  
  278. The result is an absolute number; the difference between the two 
  279. operands.  
  280.  
  281. Subtraction is also allowed between floating-point numbers; the 
  282. answer is the floating-point difference.
  283.  
  284.  
  285. Multiplication and Division
  286.  
  287. Syntax:
  288.   Multiplication: operand * operand
  289.   Division:       operand / operand
  290.   Modulo:         operand MOD operand --(absolute operands only)
  291.  
  292. You may only use these operators with absolute or floating-point 
  293. numbers, and the result is always the same type.  Either operand 
  294. may be a numeric expression, as long as the expression evaluates 
  295. to an absolute or floating-point number.  Examples: 
  296.  
  297. CMP AL,2 * 4    ; compare AL to 8
  298. MOV BX,0123/16  ; BX = 012
  299. DT  1.0 / 7.0
  300.  
  301.  
  302.  
  303. Shifting Operators
  304.  
  305. Syntax: Shift right: operand SHR count
  306.         Shift left: operand SHL count
  307.         Bit number: BIT count
  308.  
  309. The shift operators will perform a "bit-wise" shift of the 
  310. operand.  The operand will be shifted "count" bits either to the 
  311. right or the left.  Bits shifted into the operand will be set to 
  312. 0.  
  313.  
  314. The expression "BIT count" is equivalent to "1 SHL count"; i.e., 
  315. BIT returns the mask of the single bit whose number is "count".  
  316. The operands must be numeric expressions that evaluate to 
  317. absolute numbers.  Examples: 
  318.  
  319. MOV BX, 0FACBH SHR 4   ; BX = 0FACH
  320. OR AL,BIT 6            ; AL = AL OR 040; 040 is the mask for bit 6
  321.                                                           8-7
  322.  
  323. Logical Operators
  324. ------- ---------
  325. Syntax: operand OR operand
  326.         operand XOR operand
  327.         operand AND operand
  328.         NOT operand
  329.  
  330. The logical operators may only be used with absolute numbers.  
  331. They always return an absolute number.  
  332.  
  333. Logical operators operate on individual bits.   Each bit of the 
  334. answer depends only on the corresponding bit in the operand(s).  
  335.  
  336. The functions performed are as follows:
  337.  
  338. 1.  OR: An answer bit is 1 if either or both of the operand bits 
  339.     is 1.   An answer bit is 0 only if both operand bits are 0.   
  340.  
  341. Example: 
  342.  
  343. 11110000xB OR 00110011xB = 11110011xB
  344.  
  345.  
  346. 2.  XOR: This is "exclusive OR."  An answer bit is 1 if the operand bits are
  347.     different; an answer bit is 0 if the operand bits are the 
  348.     same.   Example: 
  349.  
  350. 11110000xB XOR 00110011xB = 11000011xB
  351.  
  352.  
  353. 3.  AND: An answer bit is 1 only if both operand bits are 1.   An 
  354.     answer bit is 0 if either or both operand bits are 0.   
  355.     Example: 
  356.  
  357. 11110000xB AND 00110011xB = 00110000xB
  358.  
  359. 4.  NOT: An answer bit is the opposite of the operand bit.   It 
  360.     is 1 if the operand bit is 0; 0 if the operand bit is 1.   
  361.     Example: 
  362.  
  363. NOT 00110011xB = 11001100xB
  364.  
  365.  
  366. Relational Operators
  367. ---------- ---------
  368. Syntax:
  369.   equal:            operand EQ operand
  370.   not equal:        operand NE operand
  371.   less than:        operand LT operand
  372.   less or equal:    operand LE operand
  373.   greater than:     operand GT operand
  374.   greater or equal: operand GE operand
  375.                                                           8-8
  376. The relational operators may have operands that are:
  377.  
  378. a.  both absolute numbers
  379. b.  variable names that have the same type
  380.  
  381. The result of a relational operation is always an absolute 
  382. number.  They return an 8-or 16-bit result of all 1's for TRUE 
  383. and all 0's for FALSE.  Examples: 
  384.  
  385. MOV AL, 3 EQ 0     ; AL = 0 (false)
  386. MOV AX, 2 LE 15    ; AX = 0FFFFH (true)
  387.  
  388.  
  389. Attribute Operators/Specifiers
  390. --------- --------------------
  391. B,W,D,Q,T memory-variable specifiers
  392.  
  393. Syntax: B operand          Q operand
  394.         operand B          operand Q
  395.         W operand          T operand
  396.         operand W          operand T
  397.         D operand
  398.         operand D
  399.  
  400. B, W, D, F, Q, and T convert the operand into a byte, word, 
  401. doubleword, far, quadword, and ten-byte variable, respectively.  
  402. The operand can be a constant, or a variable of the other type.  
  403. Examples: 
  404.  
  405. ARRAY_PTR:
  406.   DB 100 DUP (?)
  407. WVAR  DW ?
  408.   MOV AL,ARRAY_PTR B ; load first byte of ARRAY_PTR array into AL
  409.   MOV AL,WVAR B      ; load the low byte of WVAR into AL
  410.   MOV AX,W[01000]    ; load AX with the memory-word at loc. 01000
  411.   LDS BX,D[01000]    ; load DS:BX with the doubleword at loc. 01000
  412.   JMP F[01000]       ; jump far to the 4-byte location at 01000
  413.   FLD T[BX]          ; load ten-byte number at [BX] to 87 stack
  414.  
  415.  
  416. For compatibility with Intel/IBM assemblers, A86 accepts the more 
  417. verbose synonyms BYTE, WORD, DWORD, FAR, QWORD, and TBYTE for 
  418. B,W,D,F,Q,T, respectively.  
  419.  
  420.  
  421. SHORT and LONG operators
  422.  
  423. Syntax:   SHORT label
  424.           LONG label
  425.  
  426. The SHORT operator is used to specify that the label referenced 
  427. by a JMP instruction is within 127 bytes of the end of the 
  428. instruction.  The LONG operator specifies the opposite: that the 
  429. label is not within 127 bytes.  The appropriate operator can (and 
  430. sometimes must) be used if the label is forward referenced in the 
  431. instruction.  
  432.                                                           8-9
  433. When a non-local label is forward referenced, the assembler 
  434. assumes that it will require two bytes to represent the relative 
  435. offset of the label. By correctly using the SHORT operator, you 
  436. can save a byte of code when you use a forward reference. If the 
  437. label is not within the specified range, an error will occur.  
  438. The following example illustrates the use of the SHORT operator.  
  439.  
  440. JMP FWDLAB        ;three byte instruction
  441. JMP SHORT FWDLAB  ;two byte instruction
  442. JMP >L1           ; two byte instruction assumed for a local label
  443.  
  444. Because the assembler assumes that a forward-reference local 
  445. label is SHORT, you may sometimes be forced to override this 
  446. assumption if the label is in fact not within 127 bytes of the 
  447. JMP.  This is why LONG is provided: 
  448.  
  449. JMP LONG >L9      ; three byte instruction
  450.  
  451. If you are bothered by this possibility, you can specify the +L 
  452. switch, which causes A86 to pessimistically generate the three 
  453. byte JMP for all forward references, unless specifically told not 
  454. to with SHORT.
  455.  
  456. NOTE that LONG will have effect only on the operand to an 
  457. unconditional JMP instruction; not to conditional jumps.  This is 
  458. because the conditional jumps don't have 3-byte forms; the only 
  459. conditional jumps are short ones.  If you run into this problem, 
  460. then chances are your code is getting out of control--time to 
  461. rearrange, or to break off some of the intervening code into 
  462. separate procedures.  If you insist upon leaving the code intact, 
  463. you can replace the conditional jump with an "IF cond JMP".  
  464.  
  465.  
  466. OFFSET operator
  467.  
  468. Syntax: OFFSET var-name
  469.  
  470. OFFSET is used to convert a variable into the constant pointer to 
  471. the variable.  For example, if you have declared  XX DW ?, and 
  472. you want to load SI with the pointer to the variable XX, you can 
  473. code: MOV SI,OFFSET XX.  The simpler instruction MOV SI,XX moves 
  474. the variable contents of XX into SI, not the constant pointer to 
  475. XX.  
  476.  
  477.  
  478. NEAR Operator
  479.  
  480. Syntax: NEAR operand
  481.  
  482. NEAR converts the operand to have the type of a code label, as if 
  483. it were defined by appearing at the beginning of a program line 
  484. with a colon after it.  NEAR is provided mainly for compatibility 
  485. with Intel/IBM assemblers.  
  486.                                                           8-10
  487. Square Brackets Operator
  488.  
  489. Syntax: [operand]
  490.  
  491. Square brackets around an operand give the operand a memory-
  492. variable type.  Square brackets are generally used to enclose the 
  493. names of base and index registers: BX, BP, SI, and DI.  When the 
  494. size of the memory variable can be deduced from the context of 
  495. the expression, they are also used to turn numeric constants into 
  496. memory variables.  Examples: 
  497.  
  498.   MOV B[BX+50],047 ; move imm. value 047 into memory byte at BX+50
  499.   MOV AL,[050]     ; move byte at memory location 050 into AL
  500.   MOV AL,050       ; move immediate value 050 into AL
  501.  
  502.  
  503. Colon Operator
  504.  
  505. Syntax:  constant:operand
  506.          segreg:operand
  507.  
  508. The colon operator is used to attach a segment-register value to 
  509. an operand.  The segment-register value appears to the left of 
  510. the colon; the rest of the operand appears to the right of the 
  511. colon.  
  512.  
  513. There are two forms to the colon operator.  The first form has a 
  514. constant as the segment-register value.  This form is used to 
  515. create an operand to a long (inter-segment) JMP or CALL 
  516. instruction.  An example of this is the instruction JMP 0FFFF:0, 
  517. which jumps to the cold-boot reset location of the 86 processor.  
  518.  
  519. The only context other than JMP or CALL in which this first form 
  520. is legal, is as the operand to a DD directive or an EQU 
  521. directive.  The EQU case has a further restriction: the offset 
  522. (the part to the right of the colon) must have a value less than 
  523. 256.  This is because there simply isn't room in a symbol-table 
  524. entry for a segment-register value AND a 2-byte offset.  I don't 
  525. think you will be hurt by this restriction, since references to 
  526. other segments are usually to jump-tables at the beginning of 
  527. those segments.  
  528.  
  529. The second form has a segment register name to the left of the 
  530. colon.  This is the segment-override form, provided for 
  531. compatibility with Intel/IBM assemblers.  A86 will generate a 
  532. segment-override byte when it sees this form, unless the operand 
  533. to the right of the colon already has a default segment register 
  534. that is the same as the given override.  
  535.  
  536. I prefer the more explicit method of overrides, exclusive to A86: 
  537. simply place the segment register name before the instruction 
  538. mnemonic.  For example, I prefer ES MOV AL,[BX] to MOV 
  539. AL,ES:[BX].  
  540.                                                           8-11
  541. ST Operator
  542.  
  543. ST is ignored whenever it occurs in an expression.  It is 
  544. provided for compatibility with Intel and IBM assemblers.  
  545. For example, you can code FLD ST(0),ST(1), which will be taken by 
  546. A86 as FLD 0,1.
  547.  
  548.  
  549. TYPE Operator
  550.  
  551. Syntax: TYPE operand
  552.  
  553. The TYPE operator returns 1 if the operand is a byte variable; 2 
  554. if the operand is a word variable; 4 if the operand is a 
  555. doubleword variable; 8 if the operand is a quadword variable; 10 
  556. if the operand is a ten-byte variable; and the number of bytes 
  557. allocated by the structure if the operand is a structure name.  
  558.  
  559.  
  560. THIS and $ Specifiers
  561.  
  562. THIS returns the value of the current location counter.  It is 
  563. provided for compatibility with Intel/IBM assemblers.  The 
  564. dollar-sign $ is the more standard and familiar specifier for 
  565. this purpose; it is equivalent to THIS NEAR.  THIS is typically 
  566. used with the BYTE and WORD specifiers to create alternate-typed 
  567. symbols at the same memory location: 
  568.  
  569.      BVAR EQU THIS BYTE
  570.      WVAR  DW ?
  571.  
  572. I don't recommend the use of THIS.  If you wish to retain Intel-
  573. compatibility, you can use the less-verbose LABEL directive: 
  574.  
  575.       BVAR LABEL BYTE
  576.       WVAR  DW ?
  577.  
  578. If you are not concerned with compatibility to lesser assemblers, 
  579. A86 offers a variety of less-verbose forms.  The most concise is 
  580. DB without an operand: 
  581.  
  582.       BVAR DB
  583.       WVAR DW ?
  584.  
  585. If this is too cryptic for you, there is always BVAR EQU B[$].
  586.                                                           8-12
  587. Operator Precedence
  588. -------- ----------
  589.  
  590. Consider the expression 1 + 2 * 3.  When A86 sees this 
  591. expression, it could perform the multiplication first, giving an 
  592. answer of 1+6 = 7; or it could do the addition first, giving an 
  593. answer of 3*3 = 9.  In fact, A86 does the multiplication first, 
  594. because A86 assigns a higher precedence to multiplication than it 
  595. does addition.  
  596.  
  597. The following list specifies the order of precedence A86 assigns 
  598. to expression operators. All expressions are evaluated from left 
  599. to right following the precedence rules.  You may override this 
  600. order of evaluation and precedence through the use of parentheses 
  601. ().  In the example above, you could override the precedence by 
  602. parenthesizing the addition: (1+2) * 3.  
  603.  
  604. Some symbols that we have referred to as operators, are treated 
  605. by the assembler as operands having built-in values.  These 
  606. include B, W, F, $, and ST.  
  607.  
  608. If two operators are adjacent, the rightmost operator must have 
  609. precedence; otherwise, parentheses must be used.  
  610.  
  611. ---Highest Precedence---
  612.  
  613. 1.  Parenthesized expressions
  614. 2.  Period, colon for segment-override
  615. 3.  OFFSET, TYPE, and PTR
  616. 4.  HIGH, LOW, and BIT
  617. 5.  Multiplication and division: *, /, MOD, SHR, SHL
  618. 6.  Addition and subtraction: +,-
  619.      a. unary
  620.      b. binary
  621. 7.  Relational: EQ, NE, LT, LE, GT, GE
  622. 8.  Logical NOT
  623. 9.  Logical AND
  624. 10. Logical OR and XOR
  625. 11. Colon for long pointer, SHORT, LONG, and BY
  626. 12. DUP
  627.  
  628. ---Lowest Precedence---
  629.  
  630.